# coding=utf-8
"""Parse reuters feed and save in database with random user as owner"""

from datetime import timedelta, datetime
import feedparser
import urllib
from django.conf import settings
from django.db.models.fields import BooleanField
import lxml.html
from lxml.html.clean import clean_html
import os
from geopy import geocoders
from random import Random

from mitems.tools.utils import make_upload_path
from mitems.tools.logs import Log
from mitems.models import Item, ItemImage, UserProfile, Item_category, Airtime, Notification


FEEDS = {
            'entertainment': ('http://feeds.reuters.com/reuters/entertainment',),
#            'technology': ('http://feeds.reuters.com/reuters/technologyNews',),
#            'news': ( 'http://feeds.reuters.com/reuters/worldNews',
#                      'http://feeds.reuters.com/reuters/topNews' ),
            'lifestyle': ('http://feeds.reuters.com/reuters/lifestyle',),
            'sports': ('http://feeds.reuters.com/reuters/sportsNews',),
            'personal': ('http://feeds.reuters.com/reuters/oddlyEnoughNews',),
#            'business': ('http://feeds.reuters.com/reuters/businessNews',),
#            'travel': ('http://feeds.reuters.com/reuters/environment',),
}

BASE_URL= 'http://www.reuters.com/'
log = Log(settings.FEED_LOG_FILE, settings.FEED_LOG_LOGGER,
          settings.FEED_LOG_SIZE,settings.FEED_LOG_COUNT, settings.DEBUG)

FEED_ITEMS = set([ feed_id for feed_id in
                   Item.objects.filter(is_feed=True,
                                       time_expired__gt=(datetime.now()-timedelta(hours=8))).
                   values_list('feed_id', flat=True) if feed_id ]
)

BOT_USERS = list(UserProfile.objects.filter(is_bot=True))

RANDOM_AIRTIME = (40, 140)
RANDOM_MINUTES = (-24*60, 0)
FEED_EXPIRE_TIME = 14

def save_feed_image(content):
    """Save 2 picture files"""
    if not content:
        return
    filename_small = os.path.join(settings.MEDIA_ROOT, make_upload_path(None, None))
    filename_big = os.path.join(settings.MEDIA_ROOT, make_upload_path(None, None))
    try:
        with open(filename_small, 'wb+') as destination:
            destination.write(content)
        with open(filename_big, 'wb+') as destination:
            destination.write(content)
    except IOError as error:
        log.log('Cannot save image: %s' % error, 'error')
        return
    return {'small': os.path.basename(filename_small),
            'big': os.path.basename(filename_big)}


def get_random_user(users):
    if not users:
        return
    return Random().choice(users)


def get_random_time():
    return datetime.now() + timedelta(seconds=Random().randint(*RANDOM_MINUTES))


def get_feed_image(url):
    """Get picture from page"""
    parser = lxml.html.fromstring(urllib.urlopen(url).read())
    image_div = parser.get_element_by_id('articleImage', None)
    if image_div is None:
        image_div = parser.get_element_by_id('displayFrame', None)
    if image_div is None:
        return
    image_url = image_div.find('.//img')
    if image_url is not None:
        image_url.make_links_absolute(BASE_URL)
        try:
            return urllib.urlopen(image_url.get('src')).read()
        except Exception as error:
            log.log('Cannot get image: %s' % error, 'error')


def get_description(desc):
    desc = clean_html(lxml.html.fromstring(desc)).text_content()
    try:
        city_name, description = desc.split('-', 1)
    except Exception:
        city_name, description = None, desc
    return city_name.split('(')[0].strip() if city_name else city_name, description.strip()[:256]


def get_country(sity):
    """ Trying to get country from city name"""
    places = None
    try:
        gn = geocoders.GeoNames()
        places = list(gn.geocode(sity, exactly_one=False))
    except Exception as error:
        log.log('Cannot get country: %s' % error, 'error')
    if not places:
        return
    try:
        return places[0][0].split(',')[-1].strip()
    except Exception as error:
        log.log('Cannot get country: %s' % error, 'error')
        return


def feed_parse(category, category_url):
    """Parse category feed"""
    log.log('Start feed parsing for %s category' % category, 'info')
    items = []
    try:
        feed = feedparser.parse(category_url)
    except Exception as error:
        log.log('Cannot parse a feed %s: %s' % (category_url, error), 'error')
    try:
        item_category = Item_category.objects.get(category=category)
    except Item_category.DoesNotExist:
        item_category = None
    for feed_item in feed['items']:
        if feed_item.id in FEED_ITEMS:
            log.log('This %s item is present already' % feed_item.id, 'info')
            continue
        item_dict = dict(message=feed_item.title[:256], feed_id=feed_item.id[:500])
        if item_category:
            item_dict['category'] = item_category
        location, description = get_description(feed_item.description)
        if description:
            item_dict['description'] = description
        if location:
            item_dict['location'] = get_country(location)
        user = get_random_user(BOT_USERS)
        item_dict['images'] = save_feed_image(get_feed_image(feed_item.link))
        item_dict['created_by'] = user
        item_dict['updated_by'] = user
        item_dict['is_feed'] = True
        items.append(item_dict)
    return items


def feeds_parse():
    """Parse all feeds"""
    if not BOT_USERS:
        log.log('Here are no bot users', 'error')
        return
    items = []
    for category in [ (feed[0],l) for feed in FEEDS.items() for l in feed[1] ]:
        items.extend(feed_parse(*category))
    for feed_item in items:
        images = feed_item.pop('images', None)
        feed_item['created'] = feed_item['updated'] = get_random_time()
        item = Item.objects.create(**feed_item)
        airtime_count = Random().randint(*RANDOM_AIRTIME)
        Airtime(user=item.created_by, item=item, count=airtime_count).save()
        if not images:
            continue
        small_image = images.pop('small', None)
        big_image = images.pop('big', None)
        if small_image:
            ItemImage.objects.create(item=item, image=small_image, size='small')
        if big_image:
            ItemImage.objects.create(item=item, image=big_image, size='big')


def create_dummy_users():
    """Create dummy users"""
    users = [ 'user%s' % number for number in xrange(1,21) ]
    for user_name in users:
        user = UserProfile.objects.get_or_create(username=user_name, is_bot=True)[0]
        notify = Notification.objects.get_or_create(user=user)[0]
        for field in [f.name for f in notify._meta.fields if isinstance(f, BooleanField)]:
            setattr(notify, field, False)
        notify.save()


def delete_old_feeds():
    Item.objects.filter(is_feed=True, slumped=True,
                        created__lte=(datetime.now()-timedelta(days=FEED_EXPIRE_TIME))).delete()


if __name__ == '__main__':
    feeds_parse()
